package com.achievo.reportserver;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URL;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrBuilder;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultCDATA;

import com.achievo.reportserver.config.ReportDef;
import com.achievo.reportserver.config.ReportParam;


/**
 * 
 * Report Server
 * write at Jan 21, 2010
 * @author <a href="mailto:chinaoryx@gmail.com">Hyman.Zhang (Zhang Haipeng)</a>
 * @version 1.0
 * 
 *
 */
public class ReportDomUtils {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(ReportDomUtils.class);

	public Document parse(URL url) throws DocumentException {
		SAXReader reader = new SAXReader();
		Document document = reader.read(url);
		return document;
	}
	
	
	public String stringThrowable(Throwable t){
		
		PrintWriter tmpOut = null;			
		StrBuilder strBuilder = null;
		strBuilder = new StrBuilder();
		tmpOut = new PrintWriter(strBuilder.asWriter());
		t.printStackTrace(tmpOut);
		tmpOut.flush();
		return strBuilder.toString();
	}
	
	
	
	public void fillResponseDoc(Writer writer, ReportDef reportDef,  String status, String errorDesc
	) throws IOException, DocumentException {
		this.fillResponseDoc(writer, new ReportDef[]{reportDef}, status, errorDesc);
	}
	
	public void fillResponseDoc(Writer writer, ReportDef[] reportDefs,  String status, String errorDesc
			) throws IOException, DocumentException {
		Document doc = null;
		ClassLoader classloader = this.getClass().getClassLoader();
		URL url = classloader.getResource("xmltemplate/response_reportinfo.xml");
		try {
			doc = parse(url);
		} catch (DocumentException e) {
			logger.error("Parse file xmltemplate/response_reportinfo.xml error!", e);
			throw e;
		}		
		Node statusNode = doc.selectSingleNode( "//reportResponse/responseHead/status" );
		Element descNode = (Element) doc.selectSingleNode( "//reportResponse/responseHead/desc" );
		statusNode.setText(status);
		if (errorDesc != null) {
//			<![CDATA[data container]]>
			DefaultCDATA stringDesc = new DefaultCDATA(errorDesc);
			descNode.add(stringDesc);
//			descNode.setText("<![CDATA[" + errorDesc + "]]>");
		}
		
		Element reponseNode = (Element) doc.selectSingleNode( "//reportResponse/responseBody");
		
		if ("OK".equals(status)) {			
			if (reportDefs.length == 1) {
				Element reportNode = reponseNode.addElement("report");
				fillReportDef(reportDefs[0], reportNode);
			} else {
				Element reportListNode = reponseNode.addElement("reportlist");
				for (ReportDef reportDef : reportDefs) {
					Element reportNode = reportListNode.addElement("report");
					fillReportDef(reportDef, reportNode);
				}
			}
			
		}
		
		doc.write(writer);
	}
	
	
	
	
	private void fillReportDef(ReportDef reportDef, Element reportNode) {
		
		reportNode.addAttribute("reportId", reportDef.getReportId());
		reportNode.addAttribute("groupId", reportDef.getGroupId());
		reportNode.addElement("datasource").setText(reportDef.getDatasource());
		reportNode.addElement("reportType").setText(reportDef.getReportType());
		reportNode.addElement("isSync").setText(reportDef.getIsSync());
		reportNode.addElement("reportEngine").setText(reportDef.getReportEngine());
		reportNode.addElement("configFile").setText(reportDef.getFromConfigFile());		
		reportNode.addElement("realPath").setText(reportDef.getOutFileRealPathRoot() + reportDef.getOutFileName());		
		reportNode.addElement("serverLoc").setText(reportDef.getOutFileServerPathRoot() + reportDef.getOutFileName());
		
		
		List<ReportParam> paramList = reportDef.getParamList();
		if (paramList != null) {
			Element paramsEle = reportNode.addElement("params");
			for (ReportParam reportParam : paramList) {
				Element paramEle = paramsEle.addElement("param");
				String paramName = reportParam.getParamName();
				String paramType = reportParam.getParamType();
				String paramLabel = reportParam.getParamLabel();
				Object paramValue = reportParam.getParamValue();
				if (!StringUtils.isEmpty(paramName)) {
					paramEle.addElement("paramName").setText(paramName);
				}
				
				if (!StringUtils.isEmpty(paramType)) {
					paramEle.addElement("paramType").setText(paramType);
				}
				
				if (!StringUtils.isEmpty(paramLabel)) {
					paramEle.addElement("paramLabel").setText(paramLabel);
				}
				
				if (paramValue != null) {
					paramEle.addElement("paramValue").setText(paramValue.toString());
				}
				
			}
		}
	}

}
